#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
直播间问题采集工具 - 后端API服务器
实现问题采集、队列管理、webhook回调等核心功能
"""

import json
import logging
import os
import queue
import re
import threading
import time
from datetime import datetime
from typing import Dict, List, Optional

import requests
from flask import Flask, jsonify, request, Response
from flask_cors import CORS

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("live_monitor.log", encoding="utf-8"),
        logging.StreamHandler(),
    ],
)

logger = logging.getLogger(__name__)

try:
    from selenium_live_monitor import LiveDataProcessor
    from selenium_live_monitor import SeleniumLiveMonitor as DouyinLiveMonitor
except Exception as e:
    logger.warning(f"Selenium模块加载失败，使用模拟模式: {e}")
    from simple_test_monitor import LiveDataProcessor
    from simple_test_monitor import MockLiveMonitor as DouyinLiveMonitor

# 创建Flask应用
app = Flask(__name__)
CORS(app)  # 允许跨域请求

# 设置JSON响应的编码
app.config['JSON_AS_ASCII'] = False
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.config['JSONIFY_MIMETYPE'] = 'application/json; charset=utf-8'


def json_response(data, status_code=200):
    """返回正确编码的JSON响应"""
    response = Response(
        json.dumps(data, ensure_ascii=False, indent=2),
        status=status_code,
        mimetype='application/json; charset=utf-8'
    )
    return response


class QuestionQueue:
    """问题队列管理器"""

    def __init__(self):
        # 使用线程安全的队列
        self._queue = queue.Queue()
        self._questions = []  # 用于前端展示的问题列表
        self._lock = threading.Lock()

    def add_question(self, question_data: Dict):
        """添加问题到队列"""
        with self._lock:
            self._queue.put(question_data)
            # 保留最近100条问题用于前端展示
            self._questions.append(question_data)
            if len(self._questions) > 100:
                self._questions.pop(0)
        logger.info(f"问题已入队: {question_data}")

    def get_question(self) -> Optional[Dict]:
        """从队列获取问题（阻塞操作）"""
        try:
            return self._queue.get(timeout=1)
        except queue.Empty:
            return None

    def get_all_questions(self) -> List[Dict]:
        """获取所有问题（用于前端展示）"""
        with self._lock:
            return self._questions.copy()

    def queue_size(self) -> int:
        """获取队列大小"""
        return self._queue.qsize()


class WebhookSender:
    """Webhook发送器"""

    def __init__(self, webhook_url: str = None):
        self.webhook_url = webhook_url
        self.is_running = False
        self.send_thread = None
        self.stats = {
            "total_sent": 0,
            "success_count": 0,
            "failed_count": 0,
            "last_status": None,
        }

    def set_webhook_url(self, url: str):
        """设置Webhook URL"""
        self.webhook_url = url
        logger.info(f"Webhook URL已设置: {url}")

    def start_sending(self, question_queue: QuestionQueue):
        """开始发送队列中的问题"""
        if self.is_running:
            return

        self.is_running = True
        self.send_thread = threading.Thread(
            target=self._send_worker, args=(question_queue,), daemon=True
        )
        self.send_thread.start()
        logger.info("Webhook发送器已启动")

    def stop_sending(self):
        """停止发送"""
        self.is_running = False
        if self.send_thread:
            self.send_thread.join(timeout=5)
        logger.info("Webhook发送器已停止")

    def _send_worker(self, question_queue: QuestionQueue):
        """发送工作线程"""
        while self.is_running:
            if not self.webhook_url:
                time.sleep(1)
                continue

            question = question_queue.get_question()
            if question:
                self._send_webhook(question)

    def _send_webhook(self, question_data: Dict):
        """发送单个问题到Webhook"""
        if not self.webhook_url:
            return

        try:
            self.stats["total_sent"] += 1

            # 发送POST请求
            response = requests.post(
                self.webhook_url,
                json=question_data,
                timeout=10,
                headers={"Content-Type": "application/json"},
            )

            if response.status_code == 200:
                self.stats["success_count"] += 1
                self.stats["last_status"] = "success"
                logger.info(f"Webhook发送成功: {question_data['question']}")
            else:
                self.stats["failed_count"] += 1
                self.stats["last_status"] = f"failed_http_{response.status_code}"
                logger.error(
                    f"Webhook发送失败 - HTTP {response.status_code}: {question_data['question']}"
                )

        except requests.exceptions.RequestException as e:
            self.stats["failed_count"] += 1
            self.stats["last_status"] = f"failed_network"
            logger.error(f"Webhook发送失败 - 网络错误: {e}")
        except Exception as e:
            self.stats["failed_count"] += 1
            self.stats["last_status"] = f"failed_unknown"
            logger.error(f"Webhook发送失败 - 未知错误: {e}")

    def get_stats(self) -> Dict:
        """获取发送统计"""
        return self.stats.copy()


class QuestionExtractor:
    """问题提取器 - 识别以问号结尾的评论作为问题"""

    @staticmethod
    def is_question(comment: str) -> bool:
        """
        判断评论是否为问题
        只识别以双问号结尾的评论：
        - 英文双问号: ??
        - 中文双问号: ？？
        - 混合双问号: ?？ ？?
        """
        # 去除首尾空白字符
        comment = comment.strip()
        
        if not comment:
            return False
        
        # 检查长度至少为2（双问号）
        if len(comment) < 2:
            return False
        
        # 获取最后两个字符
        last_two = comment[-2:]
        
        # 只识别双问号结尾的评论
        double_question_patterns = ['??', '？？', '?？', '？?']
        
        return last_two in double_question_patterns

    @staticmethod
    def extract_question_data(comment_data: Dict) -> Dict:
        """提取问题数据"""
        # 清理问题内容：去除前后空格
        question_content = comment_data["content"].strip()
        
        return {
            "question": question_content,
            "user": comment_data["user"].strip(),
            "user_id": comment_data.get("user_id", "").strip(),
            "timestamp": comment_data["timestamp"],
            "room_id": comment_data.get("room_id", ""),
            "extracted_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        }


class ConfigManager:
    """配置管理器"""
    
    def __init__(self, config_file="config.json"):
        self.config_file = config_file
        self.default_config = {
            "room_id": "",
            "room_url": "",
            "webhook_url": "",
            "webhook_enabled": False,
            "default_room_urls": [
                "https://live.douyin.com/282622938056",
                "https://live.douyin.com/123456789"
            ],
            "supported_platforms": ["douyin"]
        }
        self.config = self.load_config()
    
    def load_config(self) -> Dict:
        """加载配置文件"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    loaded_config = json.load(f)
                    # 合并默认配置和加载的配置
                    config = self.default_config.copy()
                    config.update(loaded_config)
                    return config
            else:
                return self.default_config.copy()
        except Exception as e:
            logger.error(f"加载配置文件失败: {e}")
            return self.default_config.copy()
    
    def save_config(self):
        """保存配置到文件"""
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, indent=2, ensure_ascii=False)
            logger.info("配置已保存到文件")
        except Exception as e:
            logger.error(f"保存配置文件失败: {e}")
    
    def update_config(self, new_config: Dict):
        """更新配置"""
        self.config.update(new_config)
        self.save_config()
    
    def get_config(self) -> Dict:
        """获取配置"""
        return self.config.copy()


class LiveMonitorService:
    """直播监听服务"""

    def __init__(self):
        self.monitor = None
        self.processor = None
        self.question_queue = QuestionQueue()
        self.webhook_sender = WebhookSender()
        self.is_monitoring = False
        self.room_info = None
        self.config_manager = ConfigManager()
        self.config = self.config_manager.get_config()

    def set_config(self, config: Dict):
        """设置配置"""
        self.config.update(config)
        self.config_manager.update_config(config)
        if config.get("webhook_url"):
            self.webhook_sender.set_webhook_url(config["webhook_url"])
        logger.info(f"配置已更新: {self.config}")

    def start_monitoring(self, room_input: str) -> Dict:
        """开始监听
        
        Args:
            room_input: 直播间ID或完整URL
        """
        if self.is_monitoring:
            return {"success": False, "message": "监听器已在运行中"}

        try:
            # 处理输入：支持房间ID或完整URL
            if room_input.startswith("http"):
                room_url = room_input
                room_id = room_input.split("/")[-1]
            else:
                room_id = room_input
                room_url = f"https://live.douyin.com/{room_id}"

            # 创建监听器实例
            self.monitor = DouyinLiveMonitor(room_url)
            self.processor = LiveDataProcessor()

            # 获取房间信息
            self.room_info = self.monitor.get_room_info()

            # 注册评论处理回调
            self.monitor.add_callback("comment", self._handle_comment)

            # 启动监听（在新线程中运行）
            monitor_thread = threading.Thread(
                target=self.monitor.start_monitoring, daemon=True
            )
            monitor_thread.start()

            # 启动webhook发送器
            if self.config.get("webhook_enabled"):
                self.webhook_sender.start_sending(self.question_queue)

            self.is_monitoring = True
            self.config["room_id"] = room_id
            self.config["room_url"] = room_url

            logger.info(f"开始监听房间: {room_id} (URL: {room_url})")
            return {
                "success": True,
                "message": "监听已开始",
                "room_info": self.room_info,
            }

        except Exception as e:
            logger.error(f"启动监听失败: {e}")
            return {"success": False, "message": f"启动失败: {str(e)}"}

    def stop_monitoring(self) -> Dict:
        """停止监听"""
        if not self.is_monitoring:
            return {"success": False, "message": "监听器未运行"}

        try:
            # 停止监听器
            if self.monitor:
                self.monitor.stop_monitoring()

            # 停止webhook发送器
            self.webhook_sender.stop_sending()

            self.is_monitoring = False
            logger.info("监听已停止")
            return {"success": True, "message": "监听已停止"}

        except Exception as e:
            logger.error(f"停止监听失败: {e}")
            return {"success": False, "message": f"停止失败: {str(e)}"}

    def _handle_comment(self, comment_data: Dict):
        """处理评论数据"""
        # 检查是否为问题
        if QuestionExtractor.is_question(comment_data["content"]):
            # 提取问题数据
            question_data = QuestionExtractor.extract_question_data(comment_data)
            question_data["room_id"] = self.config.get("room_id", "")

            # 添加到问题队列
            self.question_queue.add_question(question_data)

    def get_status(self) -> Dict:
        """获取监听状态"""
        return {
            "is_monitoring": self.is_monitoring,
            "room_info": self.room_info,
            "queue_size": self.question_queue.queue_size(),
            "webhook_stats": self.webhook_sender.get_stats(),
            "config": self.config,
        }

    def get_questions(self) -> List[Dict]:
        """获取问题列表"""
        return self.question_queue.get_all_questions()


# 创建全局服务实例
live_service = LiveMonitorService()

# API路由定义


@app.route("/api/start", methods=["POST"])
def start_monitoring():
    """开始监听API"""
    try:
        data = request.get_json()
        room_input = data.get("room_id") or data.get("room_url")

        if not room_input:
            return jsonify({"success": False, "message": "房间ID或URL不能为空"}), 400

        result = live_service.start_monitoring(room_input)
        return jsonify(result)

    except Exception as e:
        logger.error(f"启动监听API错误: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@app.route("/api/stop", methods=["POST"])
def stop_monitoring():
    """停止监听API"""
    try:
        result = live_service.stop_monitoring()
        return jsonify(result)

    except Exception as e:
        logger.error(f"停止监听API错误: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@app.route("/api/status", methods=["GET"])
def get_status():
    """获取状态API"""
    try:
        status = live_service.get_status()
        return jsonify(status)

    except Exception as e:
        logger.error(f"获取状态API错误: {e}")
        return jsonify({"error": str(e)}), 500


@app.route("/api/config", methods=["GET", "POST"])
def handle_config():
    """配置管理API"""
    try:
        if request.method == "GET":
            return jsonify(live_service.config)

        elif request.method == "POST":
            data = request.get_json()
            live_service.set_config(data)

            # 如果启用了webhook，启动发送器
            if (
                data.get("webhook_enabled")
                and not live_service.webhook_sender.is_running
            ):
                live_service.webhook_sender.start_sending(live_service.question_queue)
            elif (
                not data.get("webhook_enabled")
                and live_service.webhook_sender.is_running
            ):
                live_service.webhook_sender.stop_sending()

            return jsonify({"success": True, "message": "配置已保存"})

    except Exception as e:
        logger.error(f"配置管理API错误: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@app.route("/api/questions", methods=["GET"])
def get_questions():
    """获取问题列表API"""
    try:
        questions = live_service.get_questions()
        return jsonify({"questions": questions, "total": len(questions)})

    except Exception as e:
        logger.error(f"获取问题API错误: {e}")
        return jsonify({"error": str(e)}), 500


@app.route("/api/questions/next", methods=["GET"])
def get_next_question():
    """获取下一个问题API - 队列模式，每次调用返回一个问题并从队列中移除"""
    try:
        question = live_service.question_queue.get_question()
        if question:
            return json_response({
                "success": True,
                "question": question,
                "queue_size": live_service.question_queue.queue_size()
            })
        else:
            return json_response({
                "success": False,
                "message": "队列中没有问题",
                "queue_size": 0
            })

    except Exception as e:
        logger.error(f"获取下一个问题API错误: {e}")
        return json_response({"success": False, "error": str(e)}, 500)


@app.route("/api/room-url", methods=["GET", "POST"])
def handle_room_url():
    """直播间URL配置管理"""
    try:
        if request.method == "GET":
            return jsonify({
                "room_id": live_service.config.get("room_id", ""),
                "room_url": live_service.config.get("room_url", ""),
                "is_monitoring": live_service.is_monitoring
            })
        
        elif request.method == "POST":
            data = request.get_json()
            room_input = data.get("room_url") or data.get("room_id")
            
            if not room_input:
                return jsonify({"success": False, "message": "直播间URL或ID不能为空"}), 400
            
            # 验证URL格式
            if room_input.startswith("http"):
                # 验证是否为有效的抖音直播间URL
                if not ("live.douyin.com" in room_input or "webcast.amemv.com" in room_input):
                    return jsonify({"success": False, "message": "请输入有效的抖音直播间URL"}), 400
                room_url = room_input
                room_id = room_input.split("/")[-1]
            else:
                # 验证房间ID格式（数字）
                if not room_input.isdigit():
                    return jsonify({"success": False, "message": "房间ID必须为数字"}), 400
                room_id = room_input
                room_url = f"https://live.douyin.com/{room_id}"
            
            # 更新配置
            config_update = {"room_id": room_id, "room_url": room_url}
            live_service.set_config(config_update)
            
            logger.info(f"直播间URL配置已更新: {room_id} -> {room_url}")
            return jsonify({
                "success": True, 
                "message": "直播间URL配置已保存",
                "room_id": room_id,
                "room_url": room_url
            })
            
    except Exception as e:
        logger.error(f"直播间URL配置错误: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@app.route("/api/test-webhook", methods=["POST"])
def test_webhook():
    """测试Webhook连接"""
    try:
        data = request.get_json()
        webhook_url = data.get("webhook_url")

        if not webhook_url:
            return jsonify({"success": False, "message": "Webhook URL不能为空"}), 400

        # 发送测试数据
        test_data = {
            "question": "这是一个测试问题??",
            "user": "测试用户",
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "room_id": "test_room",
            "is_test": True,
        }

        response = requests.post(
            webhook_url,
            json=test_data,
            timeout=10,
            headers={"Content-Type": "application/json"},
        )

        if response.status_code == 200:
            return jsonify({"success": True, "message": "Webhook测试成功"})
        else:
            return jsonify(
                {
                    "success": False,
                    "message": f"Webhook测试失败: HTTP {response.status_code}",
                }
            )

    except requests.exceptions.RequestException as e:
        return jsonify({"success": False, "message": f"网络错误: {str(e)}"})
    except Exception as e:
        logger.error(f"测试Webhook错误: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@app.route("/health", methods=["GET"])
def health_check():
    """健康检查"""
    return jsonify(
        {
            "status": "healthy",
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "service": "live-monitor-api",
        }
    )


if __name__ == "__main__":
    print("=== 直播间问题采集工具 - API服务器 ===")
    print("正在启动服务器...")
    print("API文档:")
    print("  GET  /health           - 健康检查")
    print("  POST /api/start        - 开始监听")
    print("  POST /api/stop         - 停止监听")
    print("  GET  /api/status       - 获取状态")
    print("  GET  /api/config       - 获取配置")
    print("  POST /api/config       - 设置配置")
    print("  GET  /api/room-url     - 获取直播间URL配置")
    print("  POST /api/room-url     - 设置直播间URL配置")
    print("  GET  /api/questions      - 获取问题列表")
    print("  GET  /api/questions/next - 获取下一个问题（队列模式）")
    print("  POST /api/test-webhook   - 测试Webhook")
    print("服务器运行在: http://localhost:5000")

    app.run(host="0.0.0.0", port=5000, debug=True)
